$(function () {
    var DEFAULT_TIMEZONE = 'Asia/Shanghai';
    var DEFAULT_SORT = 'asc';
    var DEFAULT_PAGE_SIZE = '50';

    var TABLE_ROW_HTML = '<tr>' +
            '<td class="w8 index"></td>' +
            '<td class="w5"></td>' +
            '<td class="w8 overflow"></td>' +
            '<td class="w8 overflow"></td>' +
            '<td class="w20"></td>' +
            '<td class="w8"></td>' +
            '<td class="w20 overflow"></td>' +
            '<td class="w5 center"></td>' +
            '</tr>';

    var messageList = [];
    var roomFilter = {users: null, room: null};

    window.isArray = function (object) {
        return Object.prototype.toString.call(object) === '[object Array]';
    };

    window.datetimePicker = function ($control) {
        $control.datetimepicker({
            format: 'YYYY-MM-DD',
            minDate: new Date(2019, 0, 1),
            maxDate: new Date(2100, 11, 31),
            icons: {
                previous: 'fa fa-arrow-left',
                next: 'fa fa-arrow-right',
                today: 'far fa-calendar-check',
                clear: 'far fa-calendar-minus',
                close: 'far fa-calendar-times'
            }
        });
    };

    window.showPaginationBar = function (currentPage, pageCount) {
        currentPage = Math.max(parseInt(currentPage), 1);
        pageCount = Math.max(parseInt(pageCount), 1);

        var firstPage = currentPage == 1;
        var lastPage = currentPage == pageCount;
        var pages = [];
        if (pageCount <= 5) {
            for (var i = 1; i <= pageCount; i++) {
                pages.push(i);
            }
        } else if (currentPage <= 3) {
            for (var i = 1; i <= 5; i++) {
                pages.push(i);
            }
        } else if (currentPage >= pageCount - 2) {
            for (i = pageCount - 4; i <= pageCount; i++) {
                pages.push(i);
            }
        } else {
            for (i = currentPage - 2; i <= currentPage + 2; i++) {
                pages.push(i);
            }
        }

        var html = '<ul class="pagination" data-page-count="' + pageCount + '" ' +
                'data-page="' + currentPage + '">';
        html = html + '<li class="page-item' + (firstPage ? ' disabled' : '') +
                '"><a class="page-link" href="javascript:" data-page="-1">' +
                '<i class="fa fa-angle-double-left"></i></a></li>';
        html = html + '<li class="page-item' + (firstPage ? ' disabled' : '') +
                '"><a class="page-link" href="javascript:" data-page="-2">' +
                '<i class="fa fa-angle-left"></i></a></li>';
        for (var i = 0, count = pages.length; i < count; i++) {
            var index = pages[i];
            if (index == currentPage) {
                html = html + '<li class="page-item active">' +
                        '<span class="page-link">' + index +  '</span></li>';
            } else {
                html = html + '<li class="page-item">' +
                        '<a class="page-link" href="javascript:" data-page="' +
                        index + '">' + index + '</a></li>';
            }
        }
        html = html + '<li class="page-item' + (lastPage ? ' disabled' : '') +
                '"><a class="page-link" href="javascript:" data-page="-3">' +
                '<i class="fa fa-angle-right"></i></a></li>';
        html = html + '<li class="page-item' + (lastPage ? ' disabled' : '') +
                '"><a class="page-link" href="javascript:" data-page="-4">' +
                '<i class="fa fa-angle-double-right"></i></a></li>';
        html = html + '</ul>';

        html = html + '<div class="input-group">' +
                '<div class="input-group-prepend">' +
                '<label class="input-group-text" for="page-no-select">Page</label>' +
                '</div>' +
                '<select id="page-number-select" class="custom-select">';
        for (var i = 1; i <= pageCount; i++) {
            html = html + '<option value="' + i + '"' +
                    (i == currentPage ? ' selected' : '') + '>' + i +
                    '</option>';
        }
        html = html + '</select></div>';
        $('#pagination-bar').html(html);
        $('#pagination-bar').data('page', currentPage);
        $('#pagination-bar').data('page-count', pageCount);
        $('#search-form [name="page_number"]').val(currentPage);
    };

    window.addPaginationHandlers = function () {
        $('#pagination-bar').on('click', 'a.page-link', function () {
            var $paginationBar = $('#pagination-bar');
            var pageCount = $paginationBar.data('page-count');
            var currentPage = $paginationBar.data('page');
            var page = $(this).data('page');
            if (page == -1) {
                page = 1;
            } else if (page == -4) {
                page = pageCount;
            } else if (page == -2) {
                page = Math.max(currentPage - 1, 1);
            } else if (page == -3) {
                page = Math.min(currentPage + 1, pageCount);
            }
            $paginationBar.data('page', page);
            $('#pagination-bar').trigger('pageChange', page);
        });

        $('#pagination-bar').on('change', '#page-number-select', function () {
            var page = $('#page-number-select').val();
            $('#pagination-bar').data('page', page);
            $('#pagination-bar').trigger('pageChange', page);
        });
    };

    window.readFormData = function ($form) {
        var data = {};
        var array = $form.serializeArray();
        var dict = {};
        for (var i = 0, count = array.length; i < count; i++) {
            var value = array[i].value;
            var oldValue = null;
            if (typeof value === 'string') value = $.trim(value);
            if (dict[array[i].name]) {
                oldValue = data[array[i].name];
                if (window.isArray(oldValue)) {
                    oldValue.push(value);
                    value = oldValue;
                } else {
                    value = [oldValue, value];
                }
            } else {
                dict[array[i].name] = true;
            }
            data[array[i].name] = value;
        }
        return data;
    };

    window.showLoadingBox = function (message, minDuration, cancel, callback) {
        var $loadingBox = $('#loading-box');
        if ($loadingBox.length == 0) {
            $(document.body).append($(
                '<div id="loading-box" class="modal fade" tabindex="-1">' +
                    '<div class="modal-dialog modal-sm">' +
                        '<div class="modal-content loading-content">' +
                            '<i class="fa fa-spin fa-spinner"></i>' +
                            '<span class="loading-text"></span>' +
                        '</div>' +
                    '</div>' +
                '</div>'
            ));
            $loadingBox = $('#loading-box');
            $loadingBox.data('timeout-id', 0);
            $loadingBox.data('min-duration', 0);
            $loadingBox.data('showing-start-time', 0);
        }
        var timeoutId = $loadingBox.data('timeout-id');
        if (timeoutId > 0) {
            $loadingBox.data('timeout-id', 0);
            clearTimeoutId(timeoutId);
        }
        if (isNaN(minDuration)) minDuration = 0;
        minDuration = (isNaN(minDuration) ? 0 : minDuration);
        minDuration = Math.max(minDuration, 500);
        $loadingBox.data('min-duration', minDuration);
        $loadingBox.data('showing-start-time', new Date().getTime());
        $loadingBox.find('.loading-text').html(message);
        if (cancel) $loadingBox.off('hidden.bs.modal');
        if (typeof(callback) == 'function') {
            $loadingBox.one('hidden.bs.modal', function () {
                callback();
            });
        }
        if (!$loadingBox.hasClass('show')) {
            $loadingBox.modal({backdrop: 'static', keyboard: false});
        }
    };

    window.hideLoadingBox = function (callback) {
        var $loadingBox = $('#loading-box');
        if ($loadingBox.length == 0) {
            if (typeof(callback) == 'function') {
                callback();
            }
            return;
        }

        if (typeof(callback) == 'function') {
            if (!$loadingBox.hasClass('show')
                    && $loadingBox.data('showing-start-time') <= 0) {
                callback();
                return;
            } else {
                $loadingBox.off('hidden.bs.modal');
                $loadingBox.one('hidden.bs.modal', function() {
                    callback();
                });
            }
        }

        var timeoutId = $loadingBox.data('timeout-id');
        var minDuration = $loadingBox.data('min-duration');
        var startTime = $loadingBox.data('showing-start-time');
        if (timeoutId > 0) {
            $loadingBox.data('timeout-id', 0);
            clearTimeoutId(timeoutId);
        }
        if (minDuration <= 0) {
            if ($loadingBox.hasClass('show')) {
                $loadingBox.data('showing-start-time', 0);
                window.forceHideLoadingBox();
            }
            return;
        }

        var now = new Date().getTime();
        var milliseconds = minDuration - (now - startTime);
        if (milliseconds <= 0) {
            if ($loadingBox.hasClass('show')) {
                $loadingBox.data('showing-start-time', 0);
                window.forceHideLoadingBox();
                return;
            }
        }

        timeoutId = setTimeout(function () {
            clearTimeout(timeoutId);
            $loadingBox.data('timeout-id', 0);
            if ($loadingBox.is(':visible')) {
                $loadingBox.data('showing-start-time', 0);
                window.forceHideLoadingBox();
            }
        }, Math.max(milliseconds, 30));
        $loadingBox.data('timeout-id', timeoutId);
    };

    window.showInformationAlert = function (icon, message, title, callback) {
        var $informationAlert = $('#information-alert');
        if ($informationAlert.length == 0) {
            $(document.body).append($(
                '<div id="information-alert" class="modal fade modal-alert" tabindex="-1">' +
                    '<div class="modal-dialog">' +
                        '<div class="modal-content">' +
                            '<div class="modal-header">' +
                                '<p class="modal-title">提示信息</p>' +
                                '<button type="button" data-dismiss="modal" class="close">' +
                                    '<span>&times;</span>' +
                                '</button>' +
                            '</div>' +
                            '<div class="modal-body">' +
                                '<i class="fa modal-icon"></i>' +
                                '<p class="alert-text"></p>' +
                            '</div>' +
                            '<div class="modal-footer">' +
                                '<button class="btn" data-dismiss="modal">OK</button>' +
                            '</div>' +
                        '</div>' +
                    '</div>' +
                '</div>'
            ));
            $informationAlert = $('#information-alert');
        }

        var $alertIcon = $informationAlert.find('.modal-icon');
        var $alertText = $informationAlert.find('.alert-text');
        var $alertButton = $informationAlert.find('.btn');
        var $alertTitle = $informationAlert.find('.modal-title');
        var iconFlag = true;
        $alertIcon.removeClass('fa-info-circle');
        $alertIcon.removeClass('fa-exclamation-circle');
        $alertIcon.removeClass('fa-question-circle');
        $alertIcon.removeClass('fa-times-circle');
        $alertButton.removeClass('btn-secondary');
        $alertButton.removeClass('btn-primary');
        $alertButton.removeClass('btn-info');
        $alertButton.removeClass('btn-warning');
        $alertButton.removeClass('btn-danger');
        switch (icon) {
        case 0:
            $alertIcon.addClass('fa-info-circle');
            $alertButton.addClass('btn-primary');
            break;
        case 1:
            $alertIcon.addClass('fa-exclamation-circle');
            $alertButton.addClass('btn-warning');
            break;
        case 2:
            $alertIcon.addClass('fa-question-circle');
            $alertButton.addClass('btn-info');
            break;
        case 3:
            $alertIcon.addClass('fa-times-circle');
            $alertButton.addClass('btn-danger');
            break;
        default:
            $alertButton.addClass('btn-secondary');
            iconFlag = false;
            break;
        }

        if (iconFlag) {
            $alertIcon.show();
        } else {
            $alertIcon.hide();
        }
        $alertText.html(message);
        title = $.trim(title);
        $alertTitle.text(title == '' ? 'Information' : title);
        if (typeof(callback) == 'function') {
            $informationAlert.one('hidden.bs.modal', callback);
        }
        $informationAlert.modal({keyboard: true});
    }

    window.forceHideLoadingBox = function () {
        var $loadingBox = $('#loading-box');
        if ($loadingBox.length == 0) return;
        if (!$loadingBox.hasClass('show')) return;
        $loadingBox.modal('hide');
        var timeoutId = setTimeout(function () {
            clearTimeout(timeoutId);
            if ($loadingBox.hasClass('show')) window.forceHideLoadingBox();
        }, 30);
    };

    window.getLocalStorageValue = function (key, defaultValue) {
        if (!window.localStorage) return defaultValue;
        var value = localStorage.getItem(key);
        if (!value) value = defaultValue;
        return value;
    };

    window.setLocalStorageValue = function (key, value) {
        if (!window.localStorage) return;
        localStorage.setItem(key, value);
    };

    function getDataList(id) {
        var requestData = readFormData($('#search-form'), true);
        if (roomFilter.users) requestData.users = roomFilter.users;
        if (roomFilter.room) requestData.room = roomFilter.room;
        if (requestData.from_user === '-') requestData.from_user = '';
        if (id) requestData = {id : id};
        if (!requestData.timezone) requestData.timezone = DEFAULT_TIMEZONE;
        if (!requestData.sort) requestData.sort = DEFAULT_SORT;
        requestData.page_number = parseInt(requestData.page_number);
        requestData.page_size = parseInt(requestData.page_size);
        if (isNaN(requestData.page_size)) requestData.page_size = 50;
        if (isNaN(requestData.page_number)) requestData.page_number = 1;
        window.setLocalStorageValue('timezone', requestData.timezone);
        window.setLocalStorageValue('sort', requestData.sort);
        window.setLocalStorageValue('page_size', requestData.page_size + '');
        window.showLoadingBox('Loading ...');
        $.get('/api/get_list', requestData, function (data) {
            if (!id) window.showPaginationBar(data.page_number, data.page_count);
            window.hideLoadingBox(function () {
                if (data.list === null) {
                    window.showInformationAlert(1, 'Your session has expired. Please relogin.');
                } else {
                    if (id) {
                        if (data.list.length > 0) showDataModal(data.list[0]);
                    } else {
                        showTableData(data);
                    }
                }
            });
        });
    }

    function getDownloadUrl() {
        var requestData = readFormData($('#search-form'), true);
        if (!requestData.timezone) requestData.timezone = DEFAULT_TIMEZONE;
        if (!requestData.sort) requestData.sort = DEFAULT_SORT;
        requestData.page_size = 0;
        requestData.page_number = 1;
        window.showLoadingBox('Loading ...');
        $.get('/api/get_download_url', requestData, function (data) {
            window.hideLoadingBox(function () {
                if (data.error === 1) {
                    window.showInformationAlert(1, 'Your session has expired. Please relogin.');
                } else if (!data.url) {
                    window.showInformationAlert(3, 'An error has occured on the server.');
                } else {
                    var $a = $('<a href="' + data.url + '" target="_blank" style="display:none">download</a>');
                    $('body').append($a);
                    $a[0].click();
                    $a.remove();
                }
            });
        });
    }

    function setDefaultValues() {
        var timezone = window.getLocalStorageValue('timezone', DEFAULT_TIMEZONE);
        var sort = window.getLocalStorageValue('sort', DEFAULT_SORT);
        var pageSize = window.getLocalStorageValue('page_size', DEFAULT_PAGE_SIZE);
        $('#search-form select[name="timezone"]').val(timezone);
        $('#search-form select[name="sort"]').val(sort);
        $('#search-form select[name="page_size"]').val(pageSize);
    }

    function showDataModal(data) {
        var $typeInput = $('#data-form .message-type > input');
        var $typeGroup = $('#data-form .message-type > .input-group');
        var $fileButton = $('#data-form .file-button');
        var $file = $('#data-form .form-group.file');
        var $files = $('#data-form .form-group.files');
        var $container = $('#data-form .file-container');
        if (data.relative_id) {
            $typeInput.addClass('d-none');
            $typeGroup.removeClass('d-none');
            $typeGroup.find('a').data('relative-id', data.relative_id);
        } else {
            $typeInput.removeClass('d-none');
            $typeGroup.addClass('d-none');
            $typeGroup.find('a').data('relative-id', '');
        }
        $file.addClass('d-none');
        $files.addClass('d-none');
        $container.empty();
        if (data.file_path) {
            $fileButton.prop('href', '/file/' + data.file_path);
            $file.removeClass('d-none');
        } else {
            $fileButton.prop('href', 'javascript:');
        }
        $('#data-form .form-control').each(function (index, element) {
            var $input = $(element);
            var name = $input.prop('name');
            if (name in data) {
                $input.val(data[name]);
            } else {
                $input.val('');
            }
        });
        if (data.chat_record_files && data.chat_record_files.length > 0) {
            $.each(data.chat_record_files, function (index, url) {
                var $formGroup = $files.find('.input-group.d-none').clone();
                $container.append($formGroup);
                $formGroup.removeClass('d-none');
                $formGroup.find('input').val(url);
                $formGroup.find('a.btn').prop('href', '/file/' + url);
            });
            $files.removeClass('d-none');
        }
        $('#data-form input[name="from_user"]').data('value', data.raw_from_user);
        $('#data-form input[name="to_user_list"]').data('value', data.raw_to_user_list);
        $('#data-form input[name="room_id"]').data('value', data.room_id);
        if (!data.room_id) {
            $('#data-form input[name="room_id"]').val(data.from_user + ' / ' + data.to_user_list);
        }
        var rawData = data.raw_data;
        if (rawData) rawData = JSON.stringify(JSON.parse(rawData));
        $('#data-form [name="raw_data"]').val(rawData);
        $('#data-modal').modal();
    }

    function showTableData(data) {
        var html = '';
        var list = data.list || [];
        var count = list.length;
        messageList = list;
        $('#data-list-group table tbody').empty();
        for (var i = 0; i < count; i++) {
            var item = list[i];
            var $row = $(TABLE_ROW_HTML);
            var $toUserListSpan = createCellContent(item.to_user_list);
            var $contentSpan = createCellContent(item.content);
            $row.find('td:eq(0)').text(item.sequance);
            $row.find('td:eq(1)').text(item.action);
            $row.find('td:eq(2)').text(item.from_user);
            $row.find('td:eq(4)').text(item.message_time);
            $row.find('td:eq(5)').text(item.message_type);
            if ($toUserListSpan) {
                $row.find('td:eq(3)').html($toUserListSpan.prop('outerHTML'));
            }
            if ($contentSpan) {
                $row.find('td:eq(6)').html($contentSpan.prop('outerHTML'));
            }
            if (item.file_path) {
                var fileHtml = '<a class="media-file" target="_blank" href="/file/' + item.file_path + '"><i class="far fa-file"></i></a>';
                $row.find('td:eq(7)').html(fileHtml);
            } else {
                $row.find('td:eq(7)').text('');
            }
            html = html + $row.prop('outerHTML');
        }
        $('#data-list-group table tbody').html(html);
        $('#data-list-group table tbody [data-toggle="popover"]').popover();
    }

    function createCellContent(text) {
        var $span = null;
        if (!text) return $span;
        var $pre = $('<pre></pre>');
        $pre.text(text);
        $span = $('<span></span>');
        $span.attr('data-container', 'body');
        $span.attr('data-html', 'true');
        $span.attr('data-placement', 'left');
        $span.attr('data-toggle', 'popover');
        $span.attr('data-trigger', 'hover');
        $span.attr('data-content', $pre.prop('outerHTML'));
        $span.text(text);
        return $span;
    }

    window.datetimePicker($('.date-picker'));
    window.showPaginationBar(1, 1);
    window.addPaginationHandlers();
    setDefaultValues();

    $('.logout-menu-item').click(function () {
        $.get('/logout', null, function (data) {
            var redirectUrl = data.redirect_url || '/';
            window.location.href = redirectUrl;
        });
    });

    $('#container .download-button').click(function () {
        getDownloadUrl();
    });

    $('#search-form select[name="from_user"]').on('change', function () {
        var value = $(this).val();
        if (value !== '-') {
            $('#search-form select[name="from_user"]').find('option[value="-"]').prop('disabled', true);
            roomFilter.users = null;
            roomFilter.room = null;
        }
    });

    $('#search-form').on('keydown', function (e) {
        if (e.originalEvent.keyCode === 13) {
            e.originalEvent.cancelBubble = true;
            e.originalEvent.stopPropagation();
            e.originalEvent.preventDefault();
            $('#search-form').find('#submit-button').trigger('click');
        }
    });
    $('input').prop('autocomplete', 'off');

    $('#submit-button').click(function () {
        $('#search-form [name="page_number"]').val(1);
        getDataList();
    });

    $('#pagination-bar').on('pageChange', function (e, page) {
        $('#search-form [name="page_number"]').val(page);
        getDataList();
    });

    $('#data-list-group table tbody').on('click', 'tr', function () {
        var $target = $(event.target);
        var $a = $target.closest('a');
        if ($a.length > 0 && $a.hasClass('media-file')) return;
        var $row = $target.closest('tr');
        if ($row.length === 0) return;
        showDataModal(messageList[$row.index()]);
    });

    $('#data-form .room-button').on('click', function () {
        var fromUser = $('#data-form input[name="from_user"]').data('value');
        var toUserList = $('#data-form input[name="to_user_list"]').data('value');
        var roomId = $('#data-form input[name="room_id"]').data('value');
        if (roomId) {
            roomFilter.users = null;
            roomFilter.room = roomId;
        } else {
            roomFilter.users = [fromUser, toUserList].join(',');
            roomFilter.room = null;
        }
        $('#search-form select[name="from_user"]').find('option[value="-"]').prop('disabled', false);
        $('#search-form select[name="from_user"]').val('-');
        $('#data-modal').one('hidden.bs.modal', function () {
            getDataList();
        });
        $('#data-modal').modal('hide');
    });

    $('#data-form .message-type > .input-group a').on('click', function () {
        var relativeId = $(this).data('relative-id');
        if (relativeId) {
            $('#data-modal').one('hidden.bs.modal', function () {
                getDataList(relativeId);
            });
            $('#data-modal').modal('hide');
        }
    });

    getDataList();
});
